import requests
from io import BytesIO
from PIL import Image, ImageOps


def resize_image(image, target_size_kb, image_format):
    """
    Resize an image to a target size in KB by adjusting quality or dimensions.
    """
    target_size_bytes = target_size_kb * 1024
    img_byte_arr = BytesIO()

    if image_format == 'JPEG':
        quality = 95
        while True:
            img_byte_arr = BytesIO()
            image.save(img_byte_arr, format=image_format, quality=quality)
            size = img_byte_arr.tell()

            if size <= target_size_bytes or quality <= 10:
                break

            quality -= 5
    else:
        # For formats like PNG, adjust size by changing dimensions
        width, height = image.size
        while True:
            img_byte_arr = BytesIO()
            image.save(img_byte_arr, format=image_format)
            size = img_byte_arr.tell()

            if size <= target_size_bytes or (width <= 1 or height <= 1):
                break

            width = int(width * 0.9)
            height = int(height * 0.9)
            image = image.resize((width, height), Image.Resampling.LANCZOS)

    return img_byte_arr.getvalue()


def adjust_image_size(image_bytes, image_format, min_kb=20, max_kb=500, small_size_kb=25, large_size_kb=480):
    """
    Adjust the image size to be within the specified range, resizing if necessary.
    """
    img = Image.open(BytesIO(image_bytes))
    img_byte_arr = BytesIO()
    img.save(img_byte_arr, format=image_format)
    size_kb = len(img_byte_arr.getvalue()) / 1024

    if size_kb < min_kb:
        return resize_image(img, small_size_kb, image_format)
    elif size_kb > max_kb:
        return resize_image(img, large_size_kb, image_format)
    else:
        return img_byte_arr.getvalue()


def fetch_and_adjust_image(url):
    """
    Fetch an image from the URL and adjust its size while retaining its format.
    """
    response = requests.get(url, headers={'Content-Type': 'text/html; charset=utf-8'})
    response.encoding = 'utf-8'
    if response.status_code == 200:
        image_bytes = response.content
        img = Image.open(BytesIO(image_bytes))
        image_format = img.format  # Get the original format of the image
        adjusted_image_bytes = adjust_image_size(image_bytes, image_format)
        return adjusted_image_bytes
    else:
        raise Exception("Failed to fetch image from URL")


"""
通过图片的url地址，判断图片是不是800*800的，
如果不是800*800并且宽高或者高宽比小于10%的居中等比放大或缩小至800*800并采取多余的部分，
如果宽高比大于10%则较长的一边放大或者缩小至800px较短的一边用白底补足，然后用文件流的形式返回
"""


def resize_and_crop_image(image_url):
    # 获取图片
    response = requests.get(image_url)
    img = Image.open(BytesIO(response.content))

    # 获取图片尺寸
    width, height = img.size

    # 如果图片已经是 800x800，直接返回
    if width == 800 and height == 800:
        return img

    aspect_ratio = width / height

    # 如果长宽比差异小于 10%，按比例调整大小
    if 0.9 <= aspect_ratio <= 1.1:
        img = ImageOps.fit(img, (800, 800), Image.Resampling.LANCZOS)
    else:
        # 如果长宽比差异大于 10%
        if width > height:
            new_width = 800
            new_height = int(800 / aspect_ratio)
        else:
            new_height = 800
            new_width = int(800 * aspect_ratio)

        img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

        # 创建一个新的白色背景图片
        new_img = Image.new("RGB", (800, 800), (255, 255, 255))
        # 将调整大小后的图片粘贴到白色背景的中心
        new_img.paste(img, ((800 - new_width) // 2, (800 - new_height) // 2))
        img = new_img

    # 将图像转换为 RGB 模式，以避免 RGBA 模式带来的错误
    img = img.convert("RGB")

    # 将图片保存为字节流
    byte_io = BytesIO()
    img.save(byte_io, format='JPEG')
    byte_io.seek(0)

    return byte_io
